package com.zsy.springframework.beans.facotry.beanfactory;

import com.zsy.springframework.beans.facotry.config.BeanDefinition;
import com.zsy.springframework.beans.facotry.exception.BeansException;
import com.zsy.springframework.beans.facotry.jiekou.one.BeanPostProcessor;
import com.zsy.springframework.beans.facotry.jiekou.one.FactoryBean;
import com.zsy.springframework.beans.facotry.jiekou.three.ConfigurableBeanFactory;
import com.zsy.springframework.util.ClassUtils;

import java.util.ArrayList;
import java.util.List;

//beanfactory的最直接的，beanfactory的抽象实现类
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {


    //能够实现的就是getbean的方法
    //因为继承了DefaultSingletonBeanRegistry 的这个类，
    // 所以可以直接获取bean的信息

    //===================================================================
    private final List<BeanPostProcessor> postProcessors = new ArrayList<>();
    //============================================
    private final ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();

    //这几个方法也是复用了！！
    @Override
    public Object getBean(String beanName) throws BeansException {
        return doGetBean(beanName, null);
    }

    @Override
    public Object getBean(String beanName, Object... args) throws BeansException {
        return doGetBean(beanName, args);
    }

    @Override
    public <T> T getBean(String beanName, Class<T> requiredType) throws BeansException {
        return (T) getBean(beanName);
    }

    protected <T> T doGetBean(final String beanName, final Object[] args) {
        Object sharedInstace = getSingleton(beanName);
        if (sharedInstace != null) {
            //需要判断是不是factorybean 如果是则需要调用 FactoryBean#getObject
            return (T) getObjectForBeanInstance(sharedInstace, beanName);
        }
        //如果singleton当中没有这个bean 需要获取定义信息然后创建
        BeanDefinition beanDefinition = getBeanDefinition(beanName);

        Object bean = createBean(beanDefinition, beanName, args);
        return (T) getObjectForBeanInstance(bean, beanName);
    }

    private Object getObjectForBeanInstance(Object beanInstace, String name) {
        if (!(beanInstace instanceof FactoryBean)) {
            return beanInstace;
        }
        Object object = getCachedObjectForFactoryBean(name);
        if (object == null) {
            FactoryBean<?> factoryBean = (FactoryBean<?>) beanInstace;
            object = getObjectFromFactoryBean(factoryBean, name);
        }
        return object;
    }


    protected abstract Object createBean(BeanDefinition beanDefinition, String beanName, Object[] args);

    protected abstract BeanDefinition getBeanDefinition(String beanName);

    //===================================================================
    public List<BeanPostProcessor> getPostProcessors() {
        return this.postProcessors;
    }

    @Override
    public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
        //先remove 后添加
        postProcessors.remove(beanPostProcessor);
        postProcessors.add(beanPostProcessor);
    }

    public ClassLoader getBeanClassLoader() {
        return this.beanClassLoader;
    }


}
